/* RTC BSP 
*/

#include <stdio.h>
#include <stdlib.h>

#include "hal.h"
#include "stm32f10x_conf.h"

static void_cb rtc_callback = NULL;

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  /* Enable the RTC Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}


void RTC_Configuration(void)
{
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  PWR_BackupAccessCmd(ENABLE);  // Allow access to BKP Domain 
  BKP_DeInit();                 // Reset Backup Domain 

  RCC_LSEConfig(RCC_LSE_ON);

  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Enable the RTC Second */
  RTC_ITConfig(RTC_IT_SEC, ENABLE);

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Set RTC prescaler: set RTC period to 1sec */
  RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
}


void rtc_init(void)
{

  NVIC_Configuration();

  if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
  {
    // Backup data register value is not correct or not yet programmed (when
    //   the first time the program is executed) 

    RTC_Configuration();


    BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
  }
  else
  {
    // Check if the Power On Reset flag is set 
    if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
    {
        ;//printf("\r\n\n Power On Reset occurred....");
    }
    // Check if the Pin Reset flag is set 
    else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
    {
        ;//printf("\r\n\n External Reset occurred....");
    }

    //printf("\r\n No need to configure RTC....");
    // Wait for RTC registers synchronization 
    RTC_WaitForSynchro();

    // Enable the RTC Second 
    RTC_ITConfig(RTC_IT_SEC, ENABLE);
    // Wait until last write operation on RTC registers has finished 
    RTC_WaitForLastTask();
  }

#ifdef RTCClockOutput_Enable

  // Enable PWR and BKP clocks 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  // Allow access to BKP Domain 
  PWR_BackupAccessCmd(ENABLE);

  // Disable the Tamper Pin 
  BKP_TamperPinCmd(DISABLE); // To output RTCCLK/64 on Tamper pin, the tamper
                             //    functionality must be disabled 

  // Enable RTC Clock Output on Tamper Pin
  BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
#endif

  RCC_ClearFlag();

}


void rtc_init_cb(void_cb cb)
{
    rtc_init();
    rtc_callback = cb;
}


static size_t sys_second = 0;

size_t get_sys_seconds(void)
{
    return sys_second;
}

void RTC_IRQHandler(void)
{
    if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
    {
        RTC_ClearITPendingBit(RTC_IT_SEC);

        // Wait until last write operation on RTC registers has finished 
        RTC_WaitForLastTask();
        
        if(NULL != rtc_callback)
            rtc_callback();
        
        sys_second++;
    }
}






// end of file -----------------------------------------------------------------
